import React from 'react';
import config from 'config'
import { connect } from 'react-redux'
import { messages, queryCurrencyPrecision, deepFullCopy, mulCalculate, addCalculate } from "share/common";
import { Table, Input, InputNumber, Tag, Row, Col, Icon, message, Button, Modal, Popover } from "antd"
const InputGroup = Input.Group;
import baseService from 'share/base.service'
import errorMessage from 'share/errorMessage';
import Chooser from 'components/chooser';
import chooserData from 'share/chooserData'
import Skeleton from 'components/skeleton'
import Condition from 'components/condition'
const If = Condition.If;
import expenseReportService from 'containers/expense-report/expense-report.service'
import 'styles/expense-report/components/slide-frame-batch-apportion.scss'

class SlideFrameBatchApportion extends React.Component {
  constructor(props) {
    super(props);
    this.state = {
      loading: false,
      saveLoading: false,
      columns: [{
        title: messages('my-account.key18'/*分摊项*/), dataIndex: 'costCenterRender', width: 300,
        render: (text, record, index) => this.renderColumns(record, 'costCenterRender', index)
      }, {
        title: messages('my-account.key15'/*分摊金额*/), dataIndex: 'amount', width: 100,
        render: (text, record, index) => this.renderColumns(record, 'amount', index)
      }, {
        title: messages('my-account.key16'/*分摊比例*/), dataIndex: 'proportion', width: 100,
        render: (text, record, index) => this.renderColumns(record, 'proportion', index)
      }, {
        title: messages('common.operation')/*操作*/, dataIndex: 'operate', width: 100,
        render: (text, record, index) => this.renderColumns(record, 'operate', index)
      }],
      dataSource: [],
      currencyCode: '',
      amount: 0,
      defaultExpenseApportion: null,
    }
  }

  componentWillReceiveProps(nextProps) {
    this.getDefaultApportion(nextProps)
  }

  // 获取币种精度
  getCurrencyPrecision = () => {
    const { currencyCode } = this.state;
    return queryCurrencyPrecision(currencyCode);
  };

  // 获取默认分摊行
  getDefaultApportion = (nextProps) => {
    const { invoices, expenseReport, slideFrameVisible } = nextProps.params;
    if (invoices && invoices.length && slideFrameVisible && !this.props.slideFrameVisible) {
      let amount = 0;
      invoices.map(item => {
        amount += item.invoiceView.expenseAmount || item.invoiceView.amount
      });
      this.setState({
        loading: true,
        amount,
        currencyCode: invoices[0].invoiceView.currencyCode
      });
      expenseReportService.getBatchApportion(expenseReport.expenseReportOID, amount).then(res => {
        this.setState({
          loading: false,
          dataSource: res.data,
          defaultExpenseApportion: res.data && res.data[0]
        })
      })
    }
  };

  renderColumns = (record, attr, index) => {
    const { costCenterItemsApportion } = this.props.params;
    const { dataSource } = this.state;
    let currencyPrecision = this.getCurrencyPrecision();
    switch (attr) {
      case 'costCenterRender':
        let labels = record.apportionmentLabels || [];
        return (
          <div className="department">
            {labels.map((item, index) => {
              let color = 'blue';
              if (item.level === 'ERROR') color = 'red';
              return <Tag key={index} color={color}>{item.name}</Tag>;
            })}
            {costCenterItemsApportion.map((costCenterItem, i) => {
              let isHaveItem = false;
              let costCenterItemIndex = undefined;
              record.costCenterItems && record.costCenterItems.map((item, itemIndex) => {
                if (item.costCenterOID === costCenterItem.costCenterOID) {
                  isHaveItem = true;
                  costCenterItemIndex = itemIndex;
                }
              });
              if (isHaveItem) {
                let isDepartment = (costCenterItem.costCenterOID === '00000000-0000-0000-0000-000000000000');
                return (
                  <InputGroup key={i} className="apportion-item-group">
                    <Popover content={costCenterItem.fieldName} placement="topLeft">
                      <Input
                        defaultValue={`${costCenterItem.fieldName}:`}
                        className="apportion-item-group-title"
                        disabled
                      />
                    </Popover>
                    {this.departmentCostCenterItem(record, index, costCenterItem, costCenterItemIndex, isDepartment)}
                  </InputGroup>
                );
              }
            })}
          </div>
        );
      case 'amount':
        return (
          <InputNumber
            precision={currencyPrecision}
            step={currencyPrecision ? 1 / Math.pow(10, currencyPrecision) : 1}
            value={record.amount}
            formatter={value => (typeof value === 'number' && !isNaN(value)) ? Number(value.toFixed(currencyPrecision)) : value}
            onChange={value => this.handleChangeAmount(value, index)}
          />
        );
      case 'proportion':
        return (
          <InputNumber
            precision={2}
            step={0.01}
            min={0}
            max={100}
            value={record.proportion * 100}
            className="expense-proportion-symbol"
            formatter={value => (typeof value === 'number' && !isNaN(value)) ? Number(value.toFixed(2)) : value}
            onChange={value => this.handleChangeProportion(value, index)}
          />
        );
      case 'operate':
        return (
          <div className="apportion-operate">
            <a onClick={() => this.handleCopyApportion(record)}
               style={{ marginRight: 5 }}>
              {messages('common.copy')/*复制*/}
            </a>
            {/*只有一行分摊时不可以删除*/}
            <If value={dataSource.length > 1}>
              <a onClick={() => this.handleRemoveApportion(index)}>
                {messages('common.delete')/*删除*/}
              </a>
            </If>
          </div>
        );
      default:
        return null;
    }
  };

  // 渲染成本中心项
  departmentCostCenterItem = (record, index, constraint, costCenterIndex, isDepartment) => {
    const { profile, company } = this.props;
    const { expenseReport, invoices } = this.props.params;
    const { dataSource } = this.state;
    let apportionmentDataScope = invoices.filter(item => item.invoiceView.apportionmentDataScope === 1)[0];
    let expenseTypeId = (apportionmentDataScope || invoices[0]).invoiceView.expenseTypeId;
    let fatherHasValue = true;
    record.costCenterItems.map(item => {
      if (item.type === 'father' && !item.costCenterItemOID) {
        fatherHasValue = false;
      }
    });
    let departmentItem, costCenterItems = null;
    if (isDepartment) {
      let departmentValue = {};
      record.costCenterItems.map(item => {
        if (item.costCenterOID === constraint.costCenterOID) {
          departmentValue = item;
        }
      });
      departmentValue.departmentOid = departmentValue.costCenterItemOID;
      departmentValue.name = departmentValue.costCenterItemName;
      let name = departmentValue.costCenterItemName ? departmentValue.costCenterItemName : '';
      let extraParams = {
        companyOID: expenseReport.docCompanyOID || expenseReport.companyOID || company.companyOID,
        leafEnable: profile['department.leaf.selection.required']
      };
      departmentItem = (
        <Chooser
          type='department'
          valueKey="departmentOid"
          labelKey="name"
          single
          showClear
          itemMap
          onChange={department => this.handleChangeCostCenter(department, index, costCenterIndex)}
          value={departmentValue.costCenterItemOID ? [departmentValue] : []}
          listExtraParams={extraParams}
        />
      );
    } else {
      let chooserItem = JSON.parse(JSON.stringify(chooserData['expense_cost_center_item']));
      chooserItem.title = constraint.fieldName;
      chooserItem.searchForm = [{
        type: 'input',
        id: 'keyword',
        label: `${constraint.fieldName}${messages('my-account.key168')/*代码*/}/${messages('my-account.key167')/*名称*/}`
      }];
      chooserItem.columns = [{
        title: `${constraint.fieldName}${messages('my-account.key168')/*代码*/}`,
        dataIndex: 'code'
      }, {
        title: `${constraint.fieldName}${messages('my-account.key167')/*名称*/}`,
        dataIndex: 'name'
      }];
      chooserItem.url = `${config.baseUrl}/api/my/cost/center/items`;
      let departmentOID = expenseReport.departmentOID;
      dataSource[index].costCenterItems.map(item => {
        if (item.costCenterOID === '00000000-0000-0000-0000-000000000000') {
          departmentOID = item.costCenterItemOID || expenseReport.departmentOID;
        }
      });
      let listExtraParams = {
        costCenterOID: constraint.costCenterOID,
        userOID: expenseReport.applicantOID,
        companyOID: expenseReport.docCompanyOID,
        expenseTypeId,
        departmentOID
      };
      let value = {};
      record.costCenterItems.map(item => {
        if (item.costCenterOID === constraint.costCenterOID) {
          value = item;
        }
      });
      if (value.type === 'son') { //子成本中心取值依赖于已选的父成本中心OID
        record.costCenterItems.map(item => {
          if (item.type === 'father' && item.costCenterItemOID) {
            listExtraParams.parentCostCenterItemOID = item.costCenterItemOID;
          }
        });
      }
      value.name = value.costCenterItemName;
      let name = value.costCenterItemName ? value.costCenterItemName : '';
      costCenterItems = (
        <Chooser
          selectorItem={chooserItem}
          valueKey="costCenterItemOID"
          labelKey="name"
          single
          showClear
          itemMap
          disabled={value.type === 'son' && !fatherHasValue} //父成本中心没有值时，子成本中心不可编辑
          onChange={costCenterItem => this.handleChangeCostCenter(costCenterItem, index, costCenterIndex)}
          value={value.costCenterItemOID ? [value] : []}
          listExtraParams={listExtraParams}
        />
      );
    }
    return isDepartment ? departmentItem : costCenterItems;
  };

  //获取实际的分摊金额
  getActualApportionAmount = () => {
    let { amount } = this.state;
    let currencyPrecision = this.getCurrencyPrecision() || 2;
    return Number(amount.toFixed(currencyPrecision));
  };

  // 修改成本中心
  handleChangeCostCenter = (result, index, costCenterIndex) => {
    if (result) {
      if (result.length === 0) {
        result[0] = {};
      }
      let { dataSource } = this.state;
      let costCenterItems = dataSource[index].costCenterItems[costCenterIndex];
      if (costCenterItems) {
        let name = result[0].name;
        if (costCenterItems.costCenterOID === '00000000-0000-0000-0000-000000000000') {
          result[0].costCenterItemOID = result[0].departmentOid;
          if (!this.props.profile || !this.props.profile['department.full.path.disabled']) {
            name = result[0].path || result[0].name;
          }
          //分摊项中有成本中心
          if (dataSource[index].costCenterItems.length > 1) {
            baseService.checkCostCenterNeedEmpty().then(res => {
              if (res.data.visible) {
                dataSource[index].costCenterItems.map(item => {
                  if (item.costCenterOID !== '00000000-0000-0000-0000-000000000000') {
                    item.costCenterItemOID = null
                  }
                });
                this.setState({ dataSource })
              }
            })
          }
        }
        if (costCenterItems.type === 'father') { //父成本中心
          //如果修改父成本中心项，则子成本中心清空
          if (result[0].costCenterItemOID !== costCenterItems.costCenterItemOID) {
            dataSource[index].costCenterItems.map(item => {
              if (item.type === 'son') {
                item.costCenterItemOID = undefined;
              }
            });
          }
        }
        costCenterItems.costCenterItemOID = result[0].costCenterItemOID;
        costCenterItems.costCenterItemName = name;
        costCenterItems.name = name;
        costCenterItems.itemCode = result[0].custDeptNumber || result[0].code;
        dataSource[index].costCenterItems[costCenterIndex] = costCenterItems;
        this.setState({ dataSource });
      }
    }
  };

  // 修改分摊金额
  handleChangeAmount = (result, index) => {
    if (typeof result === 'number' && !isNaN(result) && result !== 0) {
      let { dataSource } = this.state;
      let currencyPrecision = this.getCurrencyPrecision();
      let amount = Number(this.getActualApportionAmount().toFixed(currencyPrecision));
      dataSource[index].amount = Number((result).toFixed(currencyPrecision));
      dataSource[index].proportion = (result / amount);
      this.setState({ dataSource });
    }
  };

  // 修改分摊比例
  handleChangeProportion = (result, index) => {
    if (typeof result === 'number' && !isNaN(result)) {
      let { dataSource } = this.state;
      let amount = this.getActualApportionAmount();
      let currencyPrecision = this.getCurrencyPrecision();
      dataSource[index].proportion = result / 100;
      dataSource[index].amount = Number((result / 100 * amount).toFixed(currencyPrecision));
      this.setState({ dataSource });
    }
  };

  // 复制分摊行
  handleCopyApportion = (record) => {
    let { dataSource } = this.state;
    let target = JSON.parse(JSON.stringify(record));
    target.amount = 0;
    target.proportion = 0;
    target.apportionmentOID = null;
    target.defaultApportion = false;
    target.apportionmentOID = null;
    target.apportionmentLabels = [];
    dataSource.push(target);
    this.setState({ dataSource });
  };

  // 删除分摊行
  handleRemoveApportion = (index) => {
    let { dataSource } = this.state;
    if (index === 0 && dataSource.length > 1) {
      dataSource[1].defaultApportion = true;
      this.setState({ defaultExpenseApportion: dataSource[1] });
    }
    dataSource.splice(index, 1);
    this.setState({ dataSource });
  };

  // 新建分摊行
  handleNewExpenseApportion = () => {
    let { dataSource, defaultExpenseApportion } = this.state;
    let defaultExpense = deepFullCopy(defaultExpenseApportion);
    let accumulatorAmount = dataSource.map(item => Number(item.amount))
      .reduce((accumulator, currentValue) => accumulator + currentValue);
    const currencyPrecision = this.getCurrencyPrecision();
    const totalAmount = this.getActualApportionAmount();
    defaultExpense.amount = Math.abs(totalAmount) > Math.abs(accumulatorAmount) ? (totalAmount - accumulatorAmount).toFixed(currencyPrecision) : 0;
    defaultExpense.proportion = Math.abs(totalAmount) > Math.abs(accumulatorAmount) ? (defaultExpense.amount / totalAmount).toFixed(4) : 0;
    defaultExpense.defaultApportion = false;
    defaultExpense.costCenterItems.map(item => {
      item.costCenterItemOID = null;
      item.departmentOid = null;
      item.costCenterItemName = null;
    });
    defaultExpense.apportionmentOID = null;
    defaultExpense.apportionmentLabels = [];
    dataSource.push(defaultExpense);
    this.setState({ dataSource });
  };

  // 一键均摊功能,除不尽最后一位默认填充上
  handleAverageExpenseApportion = () => {
    let { dataSource } = this.state;
    let { length } = dataSource;
    const currencyPrecision = this.getCurrencyPrecision() || 2;
    const totalAmount = this.getActualApportionAmount();
    let handleExpenseAverage = () => {
      dataSource.map((item, index) => {
        if (index === 0) {
          item.amount = (totalAmount / length).toFixed(currencyPrecision);
          item.proportion = item.amount / totalAmount;
        } else {
          let middleAmount = dataSource
            .slice(0, index)
            .map(item => item.amount)
            .reduce((accumulator, currentValue) => Number(accumulator) - Number(currentValue), totalAmount);
          if (Math.abs(middleAmount) > 0 && Math.abs(middleAmount) <= Math.abs(totalAmount) / length) {
            item.amount = middleAmount;
          } else if (Math.abs(middleAmount) > Math.abs(totalAmount) / length) {
            index + 1 === length ? item.amount = middleAmount : item.amount = (totalAmount / length);
          } else if (totalAmount > 0 && middleAmount <= 0 || totalAmount < 0 && middleAmount >= 0) {
            item.amount = 0;
          }
          if (index <= length) {
            item.amount = item.amount.toFixed(currencyPrecision);
            item.proportion = item.amount / totalAmount;
          } else {
            item.proportion = item.amount / totalAmount;
            item.amount = item.amount.toFixed(currencyPrecision);
          }
        }
      });
      this.setState({ dataSource });
    };
    (length === 0 || length === 1) ? message.warning(messages('my-account.key190')/*请先新增分摊行*/) : handleExpenseAverage();
  };

  handleOk = () => {
    const { invoices } = this.props.params;
    const { dataSource, amount } = this.state;
    let errorType = null;
    let targetApportion = [];
    let expenseApportionAmount = 0;
    let costCenterItemName = '';
    let totalProportion = 0;
    dataSource.map((apportion, index) => {
      let tempApportion = JSON.parse(JSON.stringify(apportion));
      if (!tempApportion.costCenterItems || tempApportion.costCenterItems.length === 0) {
        errorType = 'error1'; //分摊项为空
      } else {
        let existCostCenterItems = false;
        tempApportion.costCenterItems.map(item => {
          item.costCenterItemOID && (existCostCenterItems = true);
          if (item.required && !item.costCenterItemOID) {
            errorType = 'error1'; //分摊项为空
          }
        });
        if (!existCostCenterItems) {
          errorType = 'error1'; //分摊项为空
        }
      }
      tempApportion.proportion < 0 && (tempApportion.proportion = 0);
      if (tempApportion.amount === 0 || tempApportion.proportion === 0) {
        !errorType && (errorType = 'error2'); //分摊项金额与比例为0
      }
      //金额不为0时才会有符号的比较
      if (index < dataSource.length - 1 && apportion.amount && dataSource[index + 1].amount) {
        if (apportion.amount > 0 !== dataSource[index + 1].amount > 0) {
          !errorType && (errorType = 'error3'); //分摊金额的符号不一致
        }
      }
      tempApportion.amount = (tempApportion.amount * 100).toFixed(2) / 100;
      if (-1 < tempApportion.proportion && tempApportion.proportion < 1 && tempApportion.proportion) {
        if (tempApportion.proportion.toString().split('.')[1].length > 4) {
          tempApportion.proportion = parseFloat(tempApportion.proportion.toFixed(4));
        }
      }
      expenseApportionAmount += tempApportion.amount * 100;
      tempApportion.proportion = Number(tempApportion.proportion).toFixed(4);
      totalProportion += mulCalculate(tempApportion.proportion, 10000);
      targetApportion.push(tempApportion);
    });
    //分摊行成本中心联动，如果选择了父成本中心，子成本中心不能为空
    (targetApportion || []).map(item => {
      (item.costCenterItems || []).map(costCenterItem => {
        if (costCenterItem.type === 'father' && costCenterItem.costCenterItemOID) { //父成本中心有值
          item.costCenterItems.map(costCenterItem => {
            if (costCenterItem.type === 'son' && !costCenterItem.costCenterItemOID) { //子成本中心没有值
              !errorType && (errorType = 'error4'); //父成本中心有值，子成本中心没有值
              costCenterItemName = costCenterItem.fieldName;
            }
          });
        }
      });
    });
    //判断小数加有精度问题
    if (!errorType && totalProportion !== 10000) {
      let precision = this.getCurrencyPrecision();
      if (parseFloat((expenseApportionAmount / 100).toFixed(precision)) !== parseFloat(amount.toFixed(precision))) {
        errorType = 'error5'; //分摊比例和不等于100%
      } else if (totalProportion > 9500 && totalProportion < 15000) {
        let tailNumber = targetApportion[targetApportion.length - 1].proportion;
        targetApportion[targetApportion.length - 1].proportion = addCalculate((10000 - totalProportion) / 10000, tailNumber);
      }
    }
    if (errorType) {
      const errorTypes = {
        error1: messages('expense-parent-report.key230')/*分摊项不能为空！*/,
        error2: messages('expense-parent-report.key231')/*分摊项金额与比例不能为0！*/,
        error3: messages('expense-parent-report.key232')/*分摊金额符号需一致！*/,
        error4: messages('common.please.select')/*请选择*/ + costCenterItemName,
        error5: messages('expense-parent-report.key233')/*分摊比例和需等于100%*/
      };
      Modal.error({
        title: errorTypes[errorType]
      })
    } else {
      let params = {}, invoiceOIDs = [];
      invoices.map(item => {
        invoiceOIDs.push(item.invoiceOID)
      });
      params.invoiceOIDs = invoiceOIDs;
      params.apportionPlan = {};
      params.apportionPlan.planContent = targetApportion;
      this.setState({ saveLoading: true });
      expenseReportService.saveBatchApportion(params).then(() => {
        this.setState({ saveLoading: false });
        message.success(messages('expense-parent-report.key234')/*批量分摊成功！*/);
        this.props.close();
      }).catch(e => {
        this.setState({ saveLoading: false });
        errorMessage(e.response);
      })
    }
  };

  render() {
    const { loading, saveLoading, columns, dataSource, currencyCode, amount } = this.state;
    return (
      <div className="slide-frame-batch-apportion">
        <Skeleton loading={loading}>
          <div className="amount-info">
            {messages('expense-parent-report.key235')/*分摊总金额*/}：
            <span className="amount-highlight">
              {currencyCode} {Number(amount).toFixed(this.getCurrencyPrecision())}
            </span>
          </div>
          <Table rowKey={record => record.index}
                 columns={columns}
                 dataSource={dataSource}
                 pagination={false}
                 bordered
                 size="small"/>
          <Row>
            <Col span={12}>
              <div className="apportion-buttons" onClick={this.handleNewExpenseApportion}>
                <Icon type="plus"/> {messages('expense-parent-report.key236')/*添加分摊*/}
              </div>
            </Col>
            <Col span={12}>
              <div className="apportion-buttons" onClick={this.handleAverageExpenseApportion}>
                {messages('my-account.key194')/*一键均摊*/}
              </div>
            </Col>
          </Row>
        </Skeleton>
        <div className="slide-footer">
          <Button type="primary" loading={saveLoading} onClick={this.handleOk}>{messages('common.ok'/*确认*/)}</Button>
          <Button onClick={this.props.close}>{messages('common.cancel')}</Button>
        </div>
      </div>
    )
  }
}

function mapStateToProps(state) {
  return {
    profile: state.login.profile,
    company: state.login.company,
    user: state.login.user,
  }
}

export default connect(mapStateToProps)(SlideFrameBatchApportion)
